package submarine;

import Common.Game;

import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

public class World extends JPanel implements Game {
    protected static final int WIDTH = 641;
    protected static final int HEIGHT = 479;
    protected Battleship ship = new Battleship();
    protected SeaObject[] submarines = {};
    protected Mine[] mines = {};
    protected Bomb[] bombs = {};
    public static final int RUNNING = 0;
    public static final int GAME_OVER = 1;
    protected int state = RUNNING;

    /**
     * 生成潜艇
     *
     * @return SeaObject submarine
     */
    public SeaObject nextSubmarine() {
        Random rand = new Random();
        int type = rand.nextInt(7);
        if (type <= 3) {
            return new MineSubmarine();
        } else if (type <= 4) {
            return new ObserveSubmarine();
        } else {
            return new TorpedoSubmarine();
        }
    }

    private int submarineEnterIndex = 0;

    /**
     * 潜艇载入
     *
     * @author xw
     */
    public void submarineEnterAction() {
        submarineEnterIndex++;
        if (submarineEnterIndex % 40 == 0) {
            this.submarines = Arrays.copyOf(this.submarines, submarines.length + 1);
            this.submarines[submarines.length - 1] = nextSubmarine();
        }
    }

    private int mineEnterIndex = 0;

    /**
     * 发射水雷
     *
     * @author xw
     */
    private void mineEnterAction() {
        mineEnterIndex++;
        if (mineEnterIndex % 100 == 0) {
            for (SeaObject seaObject :
                    submarines) {
                if (seaObject instanceof MineSubmarine) {
                    MineSubmarine submarine = (MineSubmarine) seaObject;
                    Mine mine = submarine.shootMine();
                    mines = Arrays.copyOf(mines, mines.length + 1);
                    mines[mines.length - 1] = mine;
                }
            }
        }
    }

    /**
     * 游戏对象移动
     *
     * @author xw
     */
    public void moveAction() {
        for (SeaObject submarine :
                submarines) {
            submarine.move();
        }
        for (Mine mine :
                mines) {
            mine.move();
        }
        for (Bomb bomb :
                bombs) {
            bomb.move();
        }
    }

    /**
     * 清理越界与死亡对象（防止内存泄漏）
     *
     * @author xw
     */
    public void outOfBoundsAction() {
        for (int i = 0; submarines.length > i; i++) {
            if (submarines[i].isOutOfBounds() || submarines[i].isDead()) {
                submarines[i] = submarines[submarines.length - 1];
                submarines = Arrays.copyOf(submarines, submarines.length - 1);
            }
        }
        for (int i = 0; mines.length > i; i++) {
            if (mines[i].isOutOfBounds() || mines[i].isDead()) {
                mines[i] = mines[mines.length - 1];
                mines = Arrays.copyOf(mines, mines.length - 1);
            }
        }
        for (int i = 0; bombs.length > i; i++) {
            if (bombs[i].isOutOfBounds() || bombs[i].isDead()) {
                bombs[i] = bombs[bombs.length - 1];
                bombs = Arrays.copyOf(bombs, bombs.length - 1);
            }
        }
    }

    protected int score = 0;//成绩

    /**
     * 炸弹碰撞潜艇
     *
     * @author xw
     */
    public void bombBangAction() {
        for (Bomb bomb :
                bombs) {
            for (SeaObject submarine :
                    submarines) {
                if (bomb.isLive() && submarine.isLive() && submarine.isHit(bomb)) {
                    submarine.goDead();
                    bomb.goDead();
                    if (submarine instanceof EnemyScore) {
                        score += ((EnemyScore) submarine).getScore();
                    }
                    if (submarine instanceof EnemyLife) {
                        ship.addLife(((EnemyLife) submarine).getLife());
                    }
                }
            }
        }
    }

    /**
     * 水雷碰撞战舰
     *
     * @author xw
     */
    public void mineBangAction() {
        for (Mine mine :
                mines) {
            if (mine.isLive() && ship.isHit(mine)) {
                mine.goDead();
                ship.subtractLife();
            }
        }
    }

    /**
     * 检测游戏状态
     *
     * @author xw
     */
    public void checkGameOverAction() {
        if (ship.getLife() < 0) {
            state = GAME_OVER;
        }
    }

    /**
     * 激活游戏
     *
     * @author xw
     */
    public void action() {
        KeyAdapter k = new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_SPACE) {
                    Bomb bomb = ship.shoot();
                    bombs = Arrays.copyOf(bombs, bombs.length + 1);
                    bombs[bombs.length - 1] = bomb;
                }
                if (e.getKeyCode() == KeyEvent.VK_LEFT) {
                    ship.moveLeft();
                }
                if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
                    ship.moveRight();
                }
            }
        };

        this.addKeyListener(k);

        Timer timer = new Timer();
        int interval = 10;//间隔时间 、毫秒
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                submarineEnterAction();
                mineEnterAction();
                moveAction();
                outOfBoundsAction();
                bombBangAction();
                mineBangAction();
                checkGameOverAction();
                repaint();
            }
        }, interval, interval);
    }

    /**
     * 画对象
     *
     * @param g 画笔对象
     * @author xw
     */
    public void paint(Graphics g) {
        switch (state) {
            case RUNNING:
                Images.sea.paintIcon(null, g, 0, 0);
                ship.paintImage(g);
                for (SeaObject submarine : submarines) {
                    if (submarine.isLive()) {
                        submarine.paintImage(g);
                    }
                }
                for (SeaObject mine : mines) {
                    if (mine.isLive()) {
                        mine.paintImage(g);
                    }
                }
                for (SeaObject bomb : bombs) {
                    if (bomb.isLive()) {
                        bomb.paintImage(g);
                    }
                }
                g.drawString("Score:" + score, 100, 50);
                g.drawString("Life:" + ship.getLife(), 200, 50);
                break;
            case GAME_OVER:
                Images.gameover.paintIcon(null, g, 0, 0);
                break;
        }

    }

    public static void main(String[] args) {
        World world = new World();
        world.run();
    }

    @Override
    public void run() {
        JFrame frame = new JFrame();
        World world = new World();
        world.setFocusable(true);
        frame.setTitle("潜艇大战");
        frame.add(world);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setSize(WIDTH + 16, HEIGHT + 39);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true); //会自动调用paint
        world.action();//游戏激活
    }
}
